<?
/**
 * Copyright 2007 Melange.
 *
 * This file is part of PHP-MVC.
 *
 * PHP-MVC is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * PHP-MVC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PHP-MVC; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category    Melange
 * @package     php-mvc
 * @subpackage  view
 * @copyright   Copyright (c) 2007 Jeroen Simons. All rights reserved
 * @author      Jeroen Simons <jeroen@melange.nl>
 * @link        http://www.melange.nl/
 *
 */


/**
 * Action
 *
 * @category   Melange
 * @package    php-mvc
 * @subpackage action
 * @copyright  Copyright (c) 2007 Jeroen Simons. All rights reserved
 * @license    http://www.gnu.org/licenses/licenses.html#GPL    The GNU General Public License
 */
class Action {


    /**
     * <p>An instance of <code>TokenProcessor</code> to use for token
     * functionality.</p>
     */
    private static $token = null;


    /**
     * <p>Generate a new transaction token, to be used for enforcing a single
     * request for a particular transaction.</p>
     *
     * @param request The request we are processing
     * @return The new transaction token.
     */
    protected function generateToken(Request $request) {
        if(self::$token === null) {
            require_once("mvc/util/TokenProcessor.php");
            self::$token = TokenProcessor::getInstance();
        }
        return self::$token->generateToken($request);
    }


    /**
     * <p>Return <code>true</code> if there is a transaction token stored in
     * the user's current session, and the value submitted as a request
     * parameter with this action matches it. Returns <code>false</code> under
     * any of the following circumstances:</p>
     *
     * <ul>
     *
     * <li>No session associated with this request</li>
     *
     * <li>No transaction token saved in the session</li>
     *
     * <li>No transaction token included as a request parameter</li>
     *
     * <li>The included transaction token value does not match the transaction
     * token in the user's session</li>
     *
     * </ul>
     *
     * @param request The servlet request we are processing
     * @return <code>true</code> if there is a transaction token and it is
     *         valid; <code>false</code> otherwise.
     */
    protected function isTokenValid(Request $request, $reset=false) {
        if(self::$token === null) {
            require_once("mvc/util/TokenProcessor.php");
            self::$token = TokenProcessor::getInstance();
        }
        return self::$token->isTokenValid($request, $reset);
    }


    /**
     * <p>Reset the saved transaction token in the user's session. This
     * indicates that transactional token checking will not be needed on the
     * next request that is submitted.</p>
     *
     * @param request The servlet request we are processing
     */
    protected function resetToken(Request $request) {
        if(self::$token === null) {
            require_once("mvc/util/TokenProcessor.php");
            self::$token = TokenProcessor::getInstance();
        }
        self::$token->resetToken($request);
    }


    /**
     * <p>Save a new transaction token in the user's current session, creating
     * a new session if necessary.</p>
     *
     * @param request The servlet request we are processing
     */
    protected function saveToken(Request $request) {
        if(self::$token === null) {
            require_once("mvc/util/TokenProcessor.php");
            self::$token = TokenProcessor::getInstance();
        }
        self::$token->saveToken($request);
    }



    /**
     * Retrieves any existing errors placed in the request by previous
     * actions. This method could be called instead of creating a <code>new
     * ActionMessages()</code> at the beginning of an <code>Action</code>.
     * This will prevent saveErrors() from wiping out any existing Errors
     *
     * @param request The servlet request we are processing
     * @return the Errors that already exist in the request, or a new
     *         ActionMessages object if empty.
     * @since Struts 1.2.1
     */
    protected function getErrors(Request $request) {
        $errors = $request->getAttribute(MVC::ERROR_KEY);

        if ($errors == null) {
            require_once("mvc/action/ActionMessages.php");
            $errors = new ActionMessages();
        }

        return $errors;
    }


    /**
     * <p> Retrieves any existing messages placed in the request by previous
     * actions. This method could be called instead of creating a <code>new
     * ActionMessages()</code> at the beginning of an <code>Action</code> This
     * will prevent saveMessages() from wiping out any existing Messages </p>
     *
     * @param request The servlet request we are processing
     * @return the Messages that already exist in the request, or a new
     *         ActionMessages object if empty.
     * @since Struts 1.2.1
     */
    protected function getMessages(Request $request) {
        $messages = $request->getAttribute(MVC::MESSAGE_KEY);

        if ($messages == null) {
            require_once("mvc/action/ActionMessages.php");
            $messages = new ActionMessages();
        }

        return $messages;
    }


    /**
     * Adds the specified messages keys into the appropriate request attribute
     * for use by the &lt;html:messages&gt; tag (if messages="true" is set),
     * if any messages are required. Initialize the attribute if it has not
     * already been. Otherwise, ensure that the request attribute is not set.
     *
     * @param request  The servlet request we are processing
     * @param messages Messages object
     */
    protected function addMessages(Request $request, ActionMessages $messages) {

        if (is_null($messages)) {
            //  bad programmer! *slap*
            return;
        }

        // get any existing messages from the request, or make a new one
        $requestMessages = $request->getAttribute(MVC::MESSAGE_KEY);

        if (requestMessages == null) {
            require_once("mvc/action/ActionMessages.php");
            $requestMessages = new ActionMessages();
        }

        // add incoming messages
        $requestMessages->addMessages(messages);

        // if still empty, just wipe it out from the request
        if (empty($requestMessages)) {
            $request->removeAttribute(MVC::MESSAGE_KEY);
            return;
        }

        // Save the messages
        $request->setAttribute(MVC::MESSAGE_KEY, $requestMessages);
    }


    /**
     * Adds the specified errors keys into the appropriate request attribute
     * for use by the &lt;html:errors&gt; tag, if any messages are required.
     * Initialize the attribute if it has not already been. Otherwise, ensure
     * that the request attribute is not set.
     *
     * @param request The servlet request we are processing
     * @param errors  Errors object
     */
    protected function addErrors(Request $request, ActionMessages $errors) {

        if ($errors == null) {
            //  bad programmer! *slap*
            return;
        }

        // get any existing errors from the request, or make a new one
        $requestErrors = $request->getAttribute(MVC::ERROR_KEY);

        if ($requestErrors == null) {
            require_once("mvc/action/ActionMessages.php");
            $requestErrors = new ActionMessages();
        }

        // add incoming errors
        $requestErrors->addMessages(errors);

        // if still empty, just wipe it out from the request
        if (empty($requestErrors)) {
            $request->removeAttribute(MVC::ERROR_KEY);
            return;
        }

        // Save the errors
        $request->setAttribute(ERROR_KEY, $requestErrors);
    }


    /**
     * <p>Save the specified error messages keys into the appropriate request
     * attribute for use by the &lt;html:errors&gt; tag, if any messages are
     * required. Otherwise, ensure that the request attribute is not
     * created.</p>
     *
     * @param request The servlet request we are processing
     * @param errors  Error messages object
     * @since Struts 1.2
     */
    protected function saveErrors(Request $request, ActionMessages $errors, $inSession=false) {

        if($inSession) {

            // Remove the error attribute if none are required
            if ((is_null($errors) || count($errors) == 0)) {
                unset($_SESSION[MVC::ERROR_KEY]);
                return;
            }

            // Save the errors we need
            $_SESSION[MVC::ERROR_KEY] = $errors;

        } else {

            // Remove any error messages attribute if none are required
            if ((is_null($errors) || count($errors) == 0)) {
                $request->removeAttribute(MVC::ERROR_KEY);
                return;
            }

            // Save the error messages we need
            $request->setAttribute(MVC::ERROR_KEY, $errors);

        }
    }


    /**
     * <p>Save the specified messages keys into the appropriate request
     * attribute for use by the &lt;html:messages&gt; tag (if messages="true"
     * is set), if any messages are required. Otherwise, ensure that the
     * request attribute is not created.</p>
     *
     * @param request  The servlet request we are processing.
     * @param messages The messages to save. <code>null</code> or empty
     *                 messages removes any existing ActionMessages in the
     *                 request.
     * @since Struts 1.1
     */
    protected function saveMessages(Request $request, ActionMessages $messages, $inSession=false) {

        if($inSession) {

            // Remove the error attribute if none are required
            if ((is_null($messages) || count($messages) == 0)) {
                unset($_SESSION[MVC::MESSAGE_KEY]);
                return;
            }

            // Save the errors we need
            $_SESSION[MVC::MESSAGE_KEY] = $messages;

        } else {

            // Remove any error messages attribute if none are required
            if ((is_null($messages) || count($messages) == 0)) {
                $request->removeAttribute(MVC::MESSAGE_KEY);
                return;
            }

            // Save the error messages we need
            $request->setAttribute(MVC::MESSAGE_KEY, $messages);

        }
    }


    /**
     * <p>Returns <code>true</code> if the current form's cancel button was
     * pressed. This method will check if the <code>CANCEL_KEY</code>
     * request attribute has been set, which normally occurs if the cancel
     * button generated by <strong>CancelTag</strong> was pressed by the user
     * in the current request. If <code>true</code>, validation performed by
     * an <strong>ActionForm</strong>'s <code>validate()</code> method will
     * have been skipped by the controller servlet.</p>
     *
     * @param request The request we are processing
     * @return <code>true</code> if the cancel button was pressed;
     *         <code>false</code> otherwise.
     */
    protected function isCancelled(Request $request) {
        return ($request->getAttribute(MVC::CANCEL_KEY) != null);
    }

}

?>